﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Reflection;
using System.Text;

namespace AssemblyProvider.Web.Entities
{
    public static class ExtensionMethods
    {
        public static string GenerateTypeString(this System.Type type)
        {
            if (type.IsGenericType)
            {
                var builder = new StringBuilder();
                var name = type.Name;
                var index = name.IndexOf("`");

                if (index != -1)
                {
                    name = name.Remove(index);
                }

                builder.Append(name);
                builder.Append(GenerateGenericArgsString(type.GetGenericArguments()));

                return builder.ToString();
            }
            else
            {
                return type.Name;
            }
        }

        public static string GenerateGenericArgsString(System.Type[] arguments)
        {
            var builder = new StringBuilder("<");

            var hasComma = false;

            foreach (System.Type argument in arguments)
            {
                if (argument.IsGenericType)
                {
                    builder.Append(GenerateGenericArgsString(argument.GetGenericArguments()));
                }
                else
                {
                    builder.Append(argument.Name);
                }

                builder.Append(", ");
                hasComma = true;
            }

            if (hasComma)
            {
                builder.Remove(builder.Length - 2, 2);
            }

            builder.Append(">");

            return builder.ToString();
        }

        public static string GenerateParmString(ParameterInfo[] parameters)
        {
            var builder = new StringBuilder("(");
            var hasComma = false;

            foreach (ParameterInfo parameter in parameters)
            {
                if (parameter.ParameterType.IsByRef)
                {
                    builder.Append("ref ");
                }
                else if (parameter.IsOut)
                {
                    builder.Append("out ");
                }

                builder.Append(parameter.ParameterType.Name);

                if (parameter.ParameterType.IsArray)
                {
                    builder.Append("[]");
                }

                if (parameter.ParameterType.IsGenericType)
                {
                    builder.Append(GenerateGenericArgsString(parameter.ParameterType.GetGenericArguments()));
                }

                if (parameter.IsOptional)
                {
                    builder.Append(" = " + parameter.DefaultValue.ToString());
                }

                builder.Append(", ");
                hasComma = true;
            }

            if (hasComma)
            {
                builder.Remove(builder.Length - 2, 2);
            }

            builder.Append(")");

            return builder.ToString();
        }

        public static string GenerateName(this OperatorOperation operatorOperation)
        {
            //var method = operatorOperation.Method;
            //var name = method.Name;

            //return name + GenerateParmString(method.GetParameters());

            throw new NotImplementedException();
        }

        public static string GenerateName(this EventOperation eventOperation)
        {
            //var method = eventOperation.Method;
            //var name = method.Name;

            //return name + GenerateParmString(method.GetParameters());

            throw new NotImplementedException();
        }

        //public static string GenerateName(this DelegateOperation delegateOperation)
        //{
        //    var method = delegateOperation.Method;
        //    var name = method.Name;

        //    return name + GenerateParmString(method.GetParameters());
        //}

        public static string GenerateName(this MethodOperation methodOperation)
        {
            var method = methodOperation.Method;
            var name = method.Name;

            return name + GenerateParmString(method.GetParameters());
        }

        public static string GenerateName(this ConstructorOperation constructorOperation)
        {
            var constructor = constructorOperation.Constructor;
            var name = constructor.Name;

            return name + GenerateParmString(constructor.GetParameters());
        }
    }
}
